package com.lxw.multidb.controller.dataharvest.dto;

import cn.tannn.jdevelops.result.bean.SerializableBean;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.*;

import java.util.List;

/**
 * 数据收割-数据库-执行参数
 * <p>
 * 定义从源数据库到目标数据库的数据迁移配置参数，包括：
 * <ul>
 *   <li>源数据库连接和表信息</li>
 *   <li>目标数据库连接和表信息</li>
 *   <li>查询条件和排序规则</li>
 *   <li>字段映射规则</li>
 * </ul>
 * </p>
 *
 * @author lxw
 * @version 1.0
 * @date 2025-07-11 11:23:13
 */
@Schema(description = "数据收割-数据库-执行参数")
@ToString
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class HarvestDbDTO extends SerializableBean<HarvestDbDTO> {

    // ==================== 源数据库配置 ====================

    /**
     * 来源数据库ID
     * <p>对应系统中已配置的数据库连接ID</p>
     */
    @Schema(description = "来源数据库ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    @NotNull(message = "来源数据库ID 不能为空")
    private Integer srcDbId;

    /**
     * 来源数据库名称
     * <p>源数据库实例中的具体数据库名称</p>
     */
    @Schema(description = "来源数据库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_db")
    @NotBlank(message = "来源数据库名称 不能为空")
    private String srcDatabase;

    /**
     * 来源表名称
     * <p>源数据库中要查询的表名</p>
     */
    @Schema(description = "来源表名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "user_info")
    @NotBlank(message = "来源表名称 不能为空")
    private String srcTableName;

    /**
     * SQL WHERE 条件
     * <p>
     * 数据筛选条件，为空则查询所有数据。
     * 注意：不需要包含 WHERE 关键字，直接写条件表达式即可。
     * </p>
     *
     * @example id > 10 AND status = '1'
     * @example create_time >= '2025-01-01'
     */
    @Schema(
            description = "SQL where 条件，为空则查所有，例如: id > 10 AND status = '1'",
            example = "status = 1 AND create_time >= '2025-01-01'"
    )
    private String srcCondition;

    /**
     * 排序字段
     * <p>
     * 用于分页查询时的排序字段，确保数据顺序一致性。
     * 建议使用主键或有索引的字段。
     * 默认值为 "id"。
     * </p>
     */
    @Schema(description = "排序字段，默认id", example = "id")
    private String srcSortField = "id";

    /**
     * 排序方式
     * <p>
     * 0 - 升序（ASC），从小到大
     * 1 - 降序（DESC），从大到小
     * 默认为0（升序）
     * </p>
     */
    @Schema(description = "排序方式（0.升序ASC，1.降序DESC，默认0）", example = "0")
    private Integer srcSortType = 0;

    // ==================== 目标数据库配置 ====================

    /**
     * 目标数据库ID
     * <p>对应系统中已配置的数据库连接ID</p>
     */
    @Schema(description = "目标数据库ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
    @NotNull(message = "目标数据库ID 不能为空")
    private Integer tgtDbId;

    /**
     * 目标数据库名称
     * <p>目标数据库实例中的具体数据库名称</p>
     */
    @Schema(description = "目标数据库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "archive_db")
    @NotBlank(message = "目标数据库名称 不能为空")
    private String tgtDatabase;

    /**
     * 目标表名称
     * <p>目标数据库中要插入数据的表名</p>
     */
    @Schema(description = "目标表名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "user_archive")
    @NotBlank(message = "目标表名称不能为空")
    private String tgtTableName;


    @Schema(description = "目标表是否新增", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
    @NotNull(message = "目标表是否新增")
    private boolean tgtNewTable;

    // ==================== 其他配置 ====================

    /**
     * 字符编码
     * <p>
     * 数据传输时使用的字符编码。
     * 常用值：UTF-8、GBK
     * </p>
     */
    @Schema(description = "编码(UTF-8、GBK)", example = "UTF-8")
    private String charset;

    /**
     * 字段映射规则
     * <p>
     * 定义源表字段到目标表字段的映射关系，包括：
     * <ul>
     *   <li>字段名称映射：源字段名 -> 目标字段名</li>
     *   <li>类型转换规则：指定目标字段类型进行自动转换</li>
     *   <li>长度限制：varchar类型的最大长度</li>
     * </ul>
     * </p>
     *
     * @see FieldRule
     */
    @Schema(description = "字段映射规则", requiredMode = Schema.RequiredMode.REQUIRED)
    @NotEmpty(message = "字段映射规则不能为空")
    @Valid
    private List<FieldRule> fieldRules;

    // ==================== 辅助方法 ====================

    /**
     * 判断是否升序排序
     *
     * @return true表示升序
     */
    public boolean isAscSort() {
        return srcSortType == null || srcSortType == 0;
    }

    /**
     * 获取有效的排序字段
     * <p>如果未设置，返回默认值 "id"</p>
     *
     * @return 排序字段名
     */
    public String getEffectiveSortField() {
        return (srcSortField != null && !srcSortField.trim().isEmpty()) ? srcSortField : "id";
    }
}